// 高阶函数
/* 
    // 满足下列两个条件
    1.函数可以作为参数被传递
    2.函数可以作为返回值输出
 */

// 把函数当作参数传递，我们可以抽离出一部分容易变化的业务逻辑，把这部分业务逻辑放在函数的参数里，这样可以分离业务代码中的变化与不变化的部分。
/* 
    // 如：向父级元素中添加100个元素，但这些元素有时全部显示有时全部隐藏，此时可以在创建100个元素时，传入一个回调函数，来控制元素的隐藏与显示
    var appendDiv = function(callback) {
        for (var i = 0; i < 100; i++) {
            var div = document.createElement('div');
            div.innerHTML = i;
            document.querySelector('.append-div-box').appendChild(div);
            callback(div);
        }
    }

    var controlDisplay = function(node) {
        node.style.display = 'none';
    }

    appendDiv(controlDisplay);

    // 如数组排序sort函数也是高阶函数
    var arr = [1,0,.1,5,4,6,7];
    arr.sort(function(a, b) {
        return a - b;
    });
    console.log(arr);
 */
/* 
    // 函数作为返回值输出
    // 让函数继续返回一个可执行的函数，延续运算过程。

    var isType = function(type) {
        return function(obj) {
            return Object.prototype.toString.call(obj) === '[object '+type+']';
        }
    };

    var isString = isType('String');
    var isArray = isType('Array');
    var isObject = isType('Object');
    var isNumber = isType('Number');
    var isBoolean = isType('Boolean');
    var isUndefined = isType('Undefined');


    console.log(
        isString('abs'), 
        isArray([]), 
        isObject({}), 
        isNumber(5), 
        isBoolean(true), 
        isString(null)
    ); // true true true true true false
    console.log(Object.prototype.toString.call(new Date()))

    var checkDataType = (function() {
        var types = ['String', 'Array', 'Function', 'Object', 'Number', 'Boolean', 'Undefined', 'Date'];
        var checkFuncs = {};

        for (var i = 0; types[i++];) {
            (function(type) {
                checkFuncs['is'+types[i]] = function(obj) {
                    return Object.prototype.toString.call(obj) === '[object '+type+']';
                }
            })(types[i])
        }

        return checkFuncs;
    })();
    console.log(checkDataType.isDate(new Date()))
 */

/* 
    // 单例模式 一旦ret 有值将不会在改变
    var getSingle = function(fn) {
        var ret;
        return function() {
            return ret || (ret = fn.apply(this, arguments));
        }
    }

    var getScript = getSingle(function() {
        return document.createElement('script')
    });
 */
